class Tools {
  convert2Zero(a) {
    return Object.is(Number(a), NaN) ? 0 : a;
  }

  floatAdd(a, b) {
    let r1;
    let r2;
    try {
      r1 = a.toString().split('.')[1].length;
    } catch (e) {
      r1 = 0;
    }
    try {
      r2 = b.toString().split('.')[1].length;
    } catch (e) {
      r2 = 0;
    }
    const m = Math.pow(10, Math.max(r1, r2));
    return ((a * m + b * m) / m).toFixed(3);
  }

  floatMul(a, b) {
    let c = 0;
    const d = a.toString();
    const e = b.toString();
    try {
      c += d.split('.')[1].length;
    } catch (f) {
      //;
    }
    try {
      c += e.split('.')[1].length;
    } catch (f) {
      //;
    }
    return (Number(d.replace('.', '')) * Number(e.replace('.', ''))) / Math.pow(10, c);
  }

  floatDiv(a, b) {
    function floatMul(A, B) {
      let c = 0;
      const d = A.toString();
      const e = B.toString();
      try {
        c += d.split('.')[1].length;
      } catch (f) {
        //;
      }
      try {
        c += e.split('.')[1].length;
      } catch (f) {
        //;
      }
      return (Number(d.replace('.', '')) * Number(e.replace('.', ''))) / Math.pow(10, c);
    }
    let c;
    let d;
    let e = 0;
    let f = 0;
    try {
      e = a.toString().split('.')[1].length;
    } catch (g) {
      //;
    }
    try {
      f = b.toString().split('.')[1].length;
    } catch (g) {
      //;
    }
    return (
      (c = Number(a.toString().replace('.', ''))),
      (d = Number(b.toString().replace('.', ''))),
      floatMul(c / d, Math.pow(10, f - e))
    );
  }

  deepCopy(obj1) {
    const type = Object.prototype.toString.call(obj1).slice(8, -1);
    let resObj;
    if (typeof obj1 === 'object') {
      if (obj1 instanceof Array) {
        resObj = [];
        for (let i = 0; i < obj1.length; i++) {
          const cur = obj1[i];
          if (typeof obj1[i] === 'object') {
            resObj[i] = this.deepCopy(obj1[i]);
          } else {
            resObj[i] = obj1[i];
          }
        }
      }
      if (type === 'Object') {
        resObj = {};
        for (const key in obj1) {
          if (typeof obj1[key] === 'object') {
            resObj[key] = this.deepCopy(obj1[key]);
          } else {
            resObj[key] = obj1[key];
          }
        }
      }
    } else {
      resObj = obj1;
    }
    return resObj;
  }

  throttle(fn, delay) {
    let endTime;
    let timer;
    const self = this;
    return function (...args) {
      const startTime = +new Date();
      if (endTime && Math.abs(endTime - startTime) < delay) {
        clearTimeout(timer);
        timer = setTimeout(() => {
          endTime = +new Date();
          fn.apply(self, args);
        }, delay);
      } else {
        endTime = +new Date();
        fn.apply(self, args);
      }
    };
  }

  guid() {
    function S4() {
      return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
    }
    return S4() + S4() + '-' + S4() + '-' + S4() + '-' + S4() + '-' + S4() + S4() + S4();
  }

  checkIfObjectEqual(objA, objB) {
    const isType = function (obj) {
      return Object.prototype.toString.call(obj).slice(8, -1);
    };

    const typeA = isType(objA);
    const typeB = isType(objB);
    if (typeA !== typeB) {
      return false;
    }
    if (typeof objA === 'object') {
      if (objA instanceof Array && objB instanceof Array) {
        if (objA.length !== objB.length) {
          return false;
        }
        if (objA.length) {
          for (let i = 0; i < objA.length; i++) {
            if (typeof objA[i] === 'object') {
              this.checkIfObjectEqual(objA[i], objB[i]);
            } else {
              if (objA[i] !== objB[i]) {
                return false;
              }
            }
          }
        } else {
          return true;
        }
      }
      if (typeA === 'Object') {
        for (const key in objA) {
          if (!Reflect.has(objB, key)) {
            return false;
          }
          if (typeof objA[key] === 'object') {
            this.checkIfObjectEqual(objA[key], objB[key]);
          } else {
            if (!objB[key]) {
              return false;
            }
            if (objA[key] !== objB[key]) {
              return false;
            }
          }
        }
      }
    } else {
      return objA === objB;
    }
    return true;
  }
}

const getTool = (() => {
  let tool;
  return () => {
    if (!tool) {
      tool = new Tools();
    }
    return tool;
  };
})();

export default getTool;
